import {
  BOOTSTRAPPING,
  LOADING_SOURCE_CODE,
  MOUNTED,
  NOT_BOOTSTRAPPED,
  NOT_LOADED,
  NOT_MOUNTED,
  UNMOUNTING,
  getAppChanges,
  shouldBeActive,
} from "../applications/app.helpers.js";
import { started } from "../start.js";
import "./navigation-events.js"
import { captureEventListeners } from "./navigation-events.js"

function flattenFnArray(fns) {
  fns = Array.isArray(fns) ? fns : [fns];
  return function (customProps) {
    // promise将多个promise组合成一个promise链
    return fns.reduce(
      (resultPromise, fn) => resultPromise.then(() => fn(customProps)),
      Promise.resolve()
    );
  };
}

function toLoadPromise(app) {
  return Promise.resolve().then(() => {
    // 只有是NOT_LOADED的时候，才需要加载
    if (app.status !== NOT_LOADED) {
      return app;
    }
    app.status = LOADING_SOURCE_CODE;
    return app.loadApp().then((val) => {
      // 获取应用的接入协议、子应用的钩子方法
      let { bootstrap, mount, unmount } = val;
      app.status = NOT_BOOTSTRAPPED;
      // 数组扁平化
      app.bootstrap = flattenFnArray(bootstrap);
      app.mount = flattenFnArray(mount);
      app.unmount = flattenFnArray(unmount);
      return app;
    });
  });
}

function toUnmountPromise(app) {
  return Promise.resolve().then(() => {
    // 如果不是挂载状态，直接跳出
    if (app.status !== MOUNTED) {
      return app;
    }
    // 标记成正在卸载，调用卸载逻辑，并标记成未挂载
    app.status = UNMOUNTING;
    return app.unmount(app.customProps).then(() => {
      app.status = NOT_MOUNTED;
    });
  });
}

function toBootStrapPromise(app) {
  return Promise.resolve().then(() => {
    if (app.status !== NOT_BOOTSTRAPPED) {
      return app;
    }
    app.status = BOOTSTRAPPING;
    return app.bootstrap(app.customProps).then(() => {
      app.status = NOT_MOUNTED;
      return app;
    });
  });
}

function toMountPromise(app) {
  return Promise.resolve().then(() => {
    if (app.status !== NOT_MOUNTED) {
      return app;
    }
    app.status = BOOTSTRAPPING;
    return app.mount(app.customProps).then(() => {
      app.status = MOUNTED;
      return app;
    });
  });
}

// 卸载完再去挂载
function tryBootstrapAndMount(app, unmountPromises) {
  // 来回切换两个子应用，正在加载的时候路径变化了，这时候不用去挂载；如果要激活，再去挂载
  return Promise.resolve().then(() => {
    if (shouldBeActive(app)) {
      return toBootStrapPromise(app).then((app) =>
        unmountPromises.then(() => {
            captureEventListeners.hashchange.forEach(item=>item())
            console.log('触发hashchange')
            toMountPromise(app)
        }));
    }
  });
}

export function reroute() {
  // 需要知道挂载、卸载哪个应用

  // 根据当前所有应用状态过滤出不同的应用类型,每次都要调用一次，每次都需要知道当前应用是否要挂载
  const { appsToLoad, appsToMount, appsToUnmount } = getAppChanges();

  if (started) {
    return performAppChanges();
  }

  // 需要去加载应用，预先加载
  //需要加载的apps
  // 应用加载就是把应用的钩子拿到（systemjs jsonp fetch等方式）
  return loadApps();

  function loadApps() {
    // const loadPromises = appsToLoad.map((app)=>{
    //     return toLoadPromise(app)
    // })
    // 和上面一样
    const loadPromises = appsToLoad.map(toLoadPromise);
    return Promise.all(loadPromises);
  }

  // 需要调用bootstrap、mount和unmount
  function performAppChanges() {
    // 应用启动了，需要卸载不需要的应用；应用可能没有加载过，启动并挂载

    const unmountPromises = Promise.all(appsToUnmount.map(toUnmountPromise));

    // toLoadPromise(app) 需要拿到加载完的app继续.then  NOT_BOOTSTRAPED
    appsToLoad.map((app) =>
      toLoadPromise(app)
        .then((app) => tryBootstrapAndMount(app, unmountPromises))
        .then(() => {
          console.log("加载完毕");
        })
    );

    //有可能start是异步加载的(start异步执行)，此时loadApp已经被调用过了，需要直接挂载就可以了
    appsToMount.map((app) =>
      tryBootstrapAndMount(app, unmountPromises).then(() => {
        console.log("加载完毕");
      })
    );
  }
}
